﻿using System;
using System.Linq;

namespace TSU.FAMC.ComputerEngineering.Classes.OrandTrees.Basis
{
    /// <summary>
    /// Base class for ORAND-tree elements.
    /// </summary>
    public class TreeElement: ICloneable
    {
        // Properties

        /// <summary>
        /// Parents interface.
        /// </summary>
        public ElementInterface Parents { get; protected set; }

        /// <summary>
        /// Children interface.
        /// </summary>
        public ElementInterface Children { get; protected set; }


        /// <summary>
        /// Abstract data, assigned to the tree element.
        /// </summary>
        public object Data;

        /// <summary>
        /// Corresponding tree element.
        /// </summary>
        public TreeElement RelatedElement;


        // Methods

        /// <summary>
        /// Default constructor.
        /// </summary>
        public TreeElement()
        {
            Parents = new ElementInterface();
            Children = new ElementInterface();
        }

        /// <summary>
        /// Links two tree elements.
        /// </summary>
        /// <param name="childElement">Child element.</param>
        /// <returns></returns>
        public void LinkChild(TreeElement childElement)
        {
            Children.Add(childElement);
            childElement.Parents.Add(this);
        }

        /// <summary>
        /// Deletes link between two elements.
        /// </summary>
        /// <param name="element">Element to delete link from/to.</param>
        public void UnlinkElement(TreeElement element)
        {
            Children.Remove(element);
            Parents.Remove(element);

            element.Children.Remove(this);
            element.Parents.Remove(this);
        }

        /// <summary>
        /// Destroys all relations between elements in all levels.
        /// </summary>
        public virtual void Destroy()
        {
            DoDestroy(this);
        }

        /// <summary>
        /// Performs element relation destroy from top to bottom recursively.
        /// </summary>
        /// <param name="currentElement">Currently destroing element.</param>
        private static void DoDestroy(TreeElement currentElement)
        {
            var children = currentElement.Children.ToList();
            foreach (var child in children)
            {
                // unlinking child element
                currentElement.UnlinkElement(child);

                // destoroing child element relations
                DoDestroy(child);
            }
        }

        /// <summary>
        /// Clones tree element.
        /// </summary>
        /// <returns>Clones the element.</returns>
        public virtual object Clone()
        {
            var clone = new TreeElement
                            {
                                Data = Data,
                                Parents = new ElementInterface(Parents),
                                Children = new ElementInterface(Children)
                            };
            return clone;
        }
    }
}
